package com.example.demo.swj;

import com.example.demo.swj.uitl.*;
import com.google.gson.Gson;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Desc描述: <br>
 * @Author: zhangfuxing
 * @Date: 2022/5/24
 **/
@RestController
@RequestMapping("/swj/demo")
public class SwjDemoApi {

    public static final String SIGN_QUESTION = "?";
    public static final String SIGN_AND = "&";
    public static final String SIGN_TYPE = "SM2";
    public static final String ENCRYPT_TYPE = "SM4";
    public static final String CHARSET_UTF8 = "UTF-8";
    private static final HostnameVerifier PROMISCUOUS_VERIFIER = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    /**
     * jdk1.7调用解析paramCert
     */
    @GetMapping("/model/v0/{paramCert}")
    public String testPost(@PathVariable String paramCert) {

        //演示环境禁用证书检查
        final RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(new SimpleClientHttpRequestFactory() {
            @Override
            protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
                if (connection instanceof HttpsURLConnection) {
                    ((HttpsURLConnection) connection).setHostnameVerifier(PROMISCUOUS_VERIFIER);
                }
                super.prepareConnection(connection, httpMethod);
            }
        });
        //1. 准备请求参数baseUrl,演示环境
        String baseUrl = "https://121.28.56.134/gateway/page/core/api/decode/params/"+paramCert;
        //2. 准备厂商秘钥信息
        String appId = "8245e1f35a5f49bc99b98d0b4689b70e";
        String appPrivateKey = "00d5411faa037c957e754488f44ed69c1a06e99ccbb18eef9f77e9a89217226754";
        String encryptKey = "4ea9e4c6b364361f8a1382b82a8469c0";
        String neuqPublicKey = "040a40cacbc9a02d444b12a5981db5ce55a115dab08bda66ae16d609ae8e2bf0356b3e9012fbbfd65d1231b77b9b952d358ad938642a2f3241af82ab6e69e219d8";

//        //3.拼接上报数据
//        SingleStatisticDTO statisticDTO = new SingleStatisticDTO();
//        statisticDTO.setReqId("20220518af42f048dc5d4fa8bd0b5sa498662ab8");
//        statisticDTO.setAppId("ed0b87bc20ac4b68a5b17392ea242e8c");
//        statisticDTO.setAppName("测试一体机");
//        statisticDTO.setItemSrc("0");
//        statisticDTO.setItemId("13880b9d85b84c1c823cd70ff48e1c58");
//        statisticDTO.setItemName("ceshi");
//        statisticDTO.setItemType("5");
//        statisticDTO.setPageId("13880b9d85b84c1c823cd70ff48e1c58");
//        statisticDTO.setAreaCode("130300");
//        statisticDTO.setAreaCodeDetail("130302003013");
//        statisticDTO.setVisit("1");
//        statisticDTO.setResult("1");
//        statisticDTO.setDesc("beizhu");
//        statisticDTO.setReqTime("20220518100000");
//        //4.上报数据加密
//        String bizContent = SMUtil.sm4Encrypt(encryptKey, new Gson().toJson(statisticDTO));
        //5.封装数据
        RequestParametersHolder holder = getRequestHolderWithSign(new HashMap<String, String>(),
                appId,
                "SM2",
                appPrivateKey,
                "SM4",
                encryptKey, null, null);
        try {
            String queryParamsString = WebUtils.buildQuery(holder.getQueryParams(), CHARSET_UTF8);
            String url = baseUrl + SIGN_QUESTION + queryParamsString;
            System.out.println("调用前1：：" + url);
            url = URLDecoder.decode(url);
            System.out.println("调用前2：：" + url);
           // System.out.println("调用前：：" + new Gson().toJson(holder.getBody()));
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.set("Content-Type", "application/json");
            HttpEntity<Object> req = new HttpEntity<Object>(holder.getBody(), httpHeaders);
            NeuqResponse result = restTemplate.getForObject(url, NeuqResponse.class);
            System.out.println("调用后：：" + new Gson().toJson(result));

            if (result.getCode().contains("NUG-1000")) {
                String signSourceData = NeuqSignature.getSignCheckContent(Converter.object2Map(result));
                //出参验签
                if (smSignValid(appId, signSourceData, result.getSign(), neuqPublicKey)) {
                    System.out.println("出参验签成功");
                }
                //出参解密
                String body= SMUtil.sm4Decrypt(encryptKey,result.getBody());
                System.out.println("出参信息主体明文："+body);
                ResultDTO dto= new Gson().fromJson(body,ResultDTO.class);
                return dto.getData();
            }
            //return result.getData();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "success";
    }


    private RequestParametersHolder getRequestHolderWithSign(Map<String, String> params,
                                                             String appId,
                                                             String signType,
                                                             String privateKey,
                                                             String encryptType,
                                                             String encryptKey,
                                                             String bizContent,
                                                             String accessToken) throws NeuqApiException {

        DefaultEncryptor encryptor = new DefaultEncryptor(encryptKey);
        DefaultSigner signer = new DefaultSigner(privateKey);

        RequestParametersHolder requestHolder = new RequestParametersHolder();
        NeuqHashMap queryParams = new NeuqHashMap();
        queryParams.put(NeuqConstants.APP_ID, appId);
        queryParams.put(NeuqConstants.SIGN_TYPE, signType);
        queryParams.put(NeuqConstants.ENCRYPT_TYPE, encryptType);
        queryParams.put(NeuqConstants.VERSION, "1.0");
        queryParams.put(NeuqConstants.ACCESS_TOKEN, accessToken);
        String queryContent = "";
        try {
            if (!params.isEmpty()) {
                queryContent = WebUtils.buildQuery(params, CHARSET_UTF8);
                queryParams.put(NeuqConstants.QUERY_CONTENT_KEY, encryptor.encrypt(queryContent, encryptType,
                        CHARSET_UTF8));
            }
        } catch (IOException e) {
            throw new NeuqApiException(e);
        }
        queryParams.put(NeuqConstants.NONCESTR, UUIDUtils.uuid());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmSS");
        queryParams.put(NeuqConstants.TIMESTAMP, sdf.format(new Date()));
        if (!StringUtils.isEmpty(bizContent)) {
            NeuqHashMap body = new NeuqHashMap();
            body.put(NeuqConstants.BIZ_CONTENT_KEY, bizContent);
            requestHolder.setBody(body);
        }
        requestHolder.setQueryParams(queryParams);

        String signContent = NeuqSignature.getSignatureContent(requestHolder);
        queryParams.put(NeuqConstants.SIGN, signer.sign(appId, signContent, signType, CHARSET_UTF8));
        return requestHolder;
    }


    public static class StrictParamKeys {

        public static final String APP_ID = "appId";
        public static final String SIGN_TYPE = "signType";
        public static final String ENCRYPT_TYPE = "encryptType";
        public static final String TIMESTAMP = "timestamp";
        public static final String VERSION = "version";
        public static final String ACCESS_TOKEN = "accessToken";
        public static final String NONCE_STR = "nonceStr";
        public static final String SIGN = "sign";

        public static final String QUERY_CONTENT = "queryContent";
        public static final String BIZ_CONTENT = "bizContent";

        /**
         * 必填参数
         */
        public static final List<String> REQUIRED_KEYS = Arrays.asList(APP_ID, SIGN_TYPE, ENCRYPT_TYPE, TIMESTAMP, VERSION, NONCE_STR, SIGN);
        /**
         * QueryParam中的参数
         */
        public static final List<String> PARAM_KEYS = Arrays.asList(APP_ID, SIGN_TYPE, ENCRYPT_TYPE, TIMESTAMP, VERSION, NONCE_STR, SIGN, ACCESS_TOKEN, QUERY_CONTENT);
        /**
         * 所有加签参数
         */
        public static final List<String> ALL_KEYS = Arrays.asList(APP_ID, SIGN_TYPE, ENCRYPT_TYPE, TIMESTAMP, VERSION, NONCE_STR, SIGN, ACCESS_TOKEN, QUERY_CONTENT, BIZ_CONTENT);

    }


    private static boolean smSignValid(String appId, String content, String sign, String publicKey) throws IOException {
        return SMUtil.sm2SignValid(publicKey, appId, content, SMUtil.sm2SignStr(sign));
    }

}
